package com.caregiver.watch.common.utils.page;

import com.caregiver.watch.common.utils.collection.ListUtils;
import com.caregiver.watch.common.utils.number.IntegerUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

import static com.caregiver.watch.common.constant.NumberConstants.ONE_INTEGER;
import static com.caregiver.watch.common.constant.NumberConstants.TEN_INTEGER;

/**
 * @Description: 分页工具
 * @Author 疆戟
 * @Date 2025/8/30 14:39
 * @Version 1.0
 */
public final class PageUtils {


    public static final String ORDER_BY_UPDATE_TIME_DESC = "update_time desc";
    public static final String ORDER_BY_UPDATE_TIME_ASC = "update_time asc";
    public static final String ORDER_BY_CREATE_TIME_DESC = "create_time desc";
    public static final String ORDER_BY_CREATE_TIME_ASC = "create_time asc";

    /**
     * 分页查询
     * @param pageNum 页码
     * @param pageSize 页大小
     * @param supplier 查询方法
     * @param <T> 泛型
     * @return 分页结果
     */
    public static <T> Page<T> selectPage(Integer pageNum, Integer pageSize, Supplier<Page<T>> supplier) {
        PageHelper.startPage(IntegerUtils.ofNullable(pageNum, ONE_INTEGER), IntegerUtils.ofNullable(pageSize, TEN_INTEGER));
        List<T> ruleList = pagingAndLoopConvert(supplier.get(), item -> item);
        return convertPage(ruleList);
    }

    /**
     * 分页查询
     * @param pageNum 页码
     * @param pageSize 页大小
     * @param supplier 查询方法
     * @param <T> 泛型
     * @return 分页结果
     */
    public static <T> Page<T> selectPage(Integer pageNum, Integer pageSize, Supplier<Page<T>> supplier, String orderBy) {
        PageHelper.startPage(IntegerUtils.ofNullable(pageNum, ONE_INTEGER), IntegerUtils.ofNullable(pageSize, TEN_INTEGER), orderBy);
        List<T> ruleList = pagingAndLoopConvert(supplier.get(), item -> item);
        return convertPage(ruleList);
    }

    /**
     * 分页查询
     * @param pageNum 页码
     * @param pageSize 页大小
     * @param supplier 查询方法
     * @param dataConvert 转换方法
     * @param orderBy 排序字段
     * @param <T> 泛型
     * @return 分页结果
     */
    public static <T,E> Page<E> selectPage(Integer pageNum, Integer pageSize, Supplier<Page<T>> supplier, Function<T, E> dataConvert, String orderBy) {
        PageHelper.startPage(IntegerUtils.ofNullable(pageNum, ONE_INTEGER), IntegerUtils.ofNullable(pageSize, TEN_INTEGER), orderBy);
        List<E> ruleList = pagingAndLoopConvert(supplier.get(), dataConvert);
        return convertPage(ruleList);
    }

    /**
     * 批量转换
     * @param list
     * @return
     * @param <T>
     */
    private static <T> Page<T> convertPage(List<T> list) {
        if (list instanceof Page) {
            return (Page)list;
        } else {
            Page<T> page = new Page();
            page.addAll(list);
            return page;
        }
    }


    /**
     * 分页和循环逐个转换
     *
     * @param prePage     转换前的分页数据
     * @param dataConvert 数据处理
     * @return com.github.pagehelper.Page<T>
     * @since 2022/10/26 11:05
     */
    private static <S, T> Page<T> pagingAndLoopConvert(Page<S> prePage, Function<S, T> dataConvert) {
        List<T> currentPageList = ListUtils.map(prePage, dataConvert);
        Page<T> pageResult = new Page<>();
        pageResult.setPageNum(prePage.getPageNum());
        pageResult.setPageSize(prePage.getPageSize());
        pageResult.setTotal(prePage.getTotal());
        pageResult.addAll(currentPageList);
        return pageResult;
    }
}
